﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Net.Http;
using System.Diagnostics;
using Microsoft.Win32;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
using Microsoft.VisualBasic;
using test;


namespace test
{
    public partial class Form1 : Form
    {

        public Form1()
        {
            InitializeComponent();
            /*绑定数据源*/
            //this.cmb_Port.DataSource = SerialPort.GetPortNames();
            //this.cmb_BaudRate.DataSource = new string[] { "9600","115200" };
            
            this.reg_write_kind.DataSource = new string[] { "Reg_Coil", "Reg_Holding" };
            this.reg_mul_write_kind.DataSource = new string[] { "Reg_Coil", "Reg_Holding" };
            

        }





















        private static ushort transactionId = 0; // 全局事务ID
        private TcpClient tcpClient;

        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {

        }

        private void label2_Click(object sender, EventArgs e)
        {

        }

        private void comboBox2_SelectedIndexChanged(object sender, EventArgs e)
        {

        }

        private void label4_Click(object sender, EventArgs e)
        {

        }

        private void label3_Click(object sender, EventArgs e)
        {

        }

        private void comboBox3_SelectedIndexChanged(object sender, EventArgs e)
        {

        }

        private void comboBox4_SelectedIndexChanged(object sender, EventArgs e)
        {
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }


        //创建一个串口对象
        // private SerialPort serialPort;
        //private void button1_Click(object sender, EventArgs e)
        //{
        //    if (this.btn_Connect_Click.Text == "建立连接")
        //    {

        //        try
        //        {
        //            serialPort = new SerialPort();
        //            //设置属性
        //            serialPort.BaudRate = Convert.ToInt32(this.cmb_BaudRate.Text);
        //            serialPort.PortName = cmb_Port.Text;

        //            //连接
        //            serialPort.Open();


        //            this.btn_Connect_Click.Text = "断开连接";
        //        }
        //        catch (Exception ex)
        //        {

        //            MessageBox.Show("连接失败：" + ex.Message);
        //            return;
        //        }


        //    }
        //    else
        //    {
        //        serialPort.Close();
        //        this.btn_Connect_Click.Text = "建立连接";
        //    }
        //}

        private void button2_Click(object sender, EventArgs e)
        {
            //读取：即发送报文
            List<byte> SendCommand = new List<byte>();

            //SendCommand.Add(Convert.ToByte(this.cmb))      
        }

        private void btn_ConnectToServer_Click_1(object sender, EventArgs e)
        {

            // 从文本框获取 IP 地址和端口号
            string ipAddress = tcpip.Text;  // 获取 IP 地址
            string portStr = tcp_port.Text;   // 获取端口号

            if (btn_ConnectToServer.Text == "连接到服务器")
            {

                if (!int.TryParse(portStr, out int port))
                {
                    MessageBox.Show("端口号无效，请输入一个有效的数字。");
                    return;
                }

                try
                {
                    tcpClient = new TcpClient();
                    tcpClient.Connect(ipAddress, port);
                    MessageBox.Show("成功连接到服务器: " + ipAddress);
                    btn_ConnectToServer.Text = "断开TCP连接";

                    //
                    


                }
                catch (Exception ex)
                {
                    MessageBox.Show("连接失败：" + ex.Message);
                }
            }

            else
            {

                tcpClient.Close();
                btn_ConnectToServer.Text = "连接到服务器";
                MessageBox.Show("已断开链接");


            }









        }
        // 验证端口号




        private void get_tcp_port(object sender, EventArgs e)
        {
            // 获取端口号
            int port;
            if (int.TryParse(tcp_port.Text, out port))
            {
                // 端口号有效
            }
            else
            {
                MessageBox.Show("请输入有效的端口号");
            }
        }

        private void get_tcpip(object sender, EventArgs e)
        {
            // 获取 IP 地址
            string ipAddress = tcpip.Text;
            if (string.IsNullOrEmpty(ipAddress))
            {
                MessageBox.Show("请输入有效的 IP 地址");
            }
        }


        private void start_address_input(object sender, EventArgs e)
        {

        }


        private void cmd_write_click(object sender, EventArgs e)
        {
            // 确保 TCP 客户端已连接
            if (tcpClient == null || !tcpClient.Connected)
            {
                MessageBox.Show("请先连接到服务器。");
                return;
            }

            byte functionCode;

            switch (reg_write_kind.Text)
            {
                case "Reg_Coil":
                    functionCode = 0x05; // 写单个线圈
                    break;

                case "Reg_Holding":
                    functionCode = 0x06; // 写单个保持寄存器
                    break;

                default:
                    MessageBox.Show("未知寄存器类型");
                    return;
            }

            ushort address = ushort.Parse(Reg_address.Text); // 寄存器地址
            ushort value = ushort.Parse(reg_write_value.Text); // 写入值

            // 如果是写线圈，只能是 0 或 1
            if (functionCode == 0x05)
            {
                if (value != 0 && value != 1)
                {
                    MessageBox.Show("线圈寄存器的值必须是 0 或 1！");
                    return;
                }
                // Modbus 协议规定：写线圈时，0xFF00 表示 ON，0x0000 表示 OFF
                value = (value == 1) ? (ushort)0xFF00 : (ushort)0x0000;
            }

            // 构建请求报文
            byte[] request = new byte[12];
            ushort transactionId = 1;
            ushort protocolId = 0;
            ushort length = 6;
            byte unitId = 1;

            request[0] = (byte)(transactionId >> 8);
            request[1] = (byte)(transactionId & 0xFF);
            request[2] = (byte)(protocolId >> 8);
            request[3] = (byte)(protocolId & 0xFF);
            request[4] = (byte)(length >> 8);
            request[5] = (byte)(length & 0xFF);
            request[6] = unitId;
            request[7] = functionCode;
            request[8] = (byte)(address >> 8);   // 地址高字节
            request[9] = (byte)(address & 0xFF); // 地址低字节
            request[10] = (byte)(value >> 8);            // 值高字节
            request[11] = (byte)(value & 0xFF);          // 值低字节

            // 发送请求
            try
            {
                NetworkStream stream = tcpClient.GetStream();
                stream.Write(request, 0, request.Length);
                MessageBox.Show("写请求已发送。");
            }
            catch (Exception ex)
            {
                MessageBox.Show("发送写请求失败：" + ex.Message);
            }


        }


        private void checkedListBox2_SelectedIndexChanged(object sender, EventArgs e)
        {
            checkedListBox1.CheckOnClick = true;
        }

        private void Reg_quality_change(object sender, EventArgs e)
        {
            int value = 0;
            checkedListBox1.Items.Clear();
            checkedListBox1.CheckOnClick = true;
            if (!int.TryParse(Reg_quality.Text, out int count) || count <= 0)
            {
                return; // 输入无效或空，清空列表
            }

            for (int i = 0; i < count; i++)
            {


                string regName = "寄存器 " + i + " = " + value;
                checkedListBox1.Items.Add(regName);
            }
        }

        private void DoubleClick_reg_selected_value(object sender, EventArgs e)
        {
            if (checkedListBox1.SelectedIndex != -1)
            {
                // 获取当前选中的项
                string currentValue = checkedListBox1.SelectedItem.ToString();

                // 提取 value
                string[] parts = currentValue.Split(new string[] { " = " }, StringSplitOptions.RemoveEmptyEntries);
                if (parts.Length == 2 && int.TryParse(parts[1], out int currentRegValue))
                {
                    // 弹出输入框获取新值
                    string newValue = Interaction.InputBox("请输入要输入寄存器的值:", "修改寄存器输入值", currentRegValue.ToString());

                    // 如果用户输入了新值，更新 CheckedListBox 项
                    if (!string.IsNullOrWhiteSpace(newValue))
                    {
                        checkedListBox1.Items[checkedListBox1.SelectedIndex] = "寄存器 " + checkedListBox1.SelectedIndex + " = " + newValue; // 更新选中的项


                    }
                }
            }
        }

        private void label9_Click(object sender, EventArgs e)
        {

        }

        /// <summary>
        /// 将 CheckedListBox 中选中的线圈状态打包成 Modbus 线圈字节数组
        /// </summary>
        private byte[] PackCoils(CheckedListBox checkedListBox, int coilCount)
        {
            int byteCount = (coilCount + 7) / 8; // 每8个线圈占1字节
            byte[] coilBytes = new byte[byteCount];

            for (int i = 0; i < coilCount; i++)
            {
                ushort value = 0;
                if (i < checkedListBox.Items.Count && checkedListBox.GetItemChecked(i))
                {
                    // 如果是 " = xxx" 格式，就取数值，否则默认=1
                    string itemText = checkedListBox.Items[i].ToString();
                    string[] parts = itemText.Split(new string[] { " = " }, StringSplitOptions.None);
                    if (parts.Length == 2 && ushort.TryParse(parts[1], out ushort regValue))
                        value = (regValue != 0) ? (ushort)1 : (ushort)0;
                    else
                        value = 1;
                }

                if (value == 1)
                {
                    int byteIndex = i / 8;
                    int bitIndex = i % 8;
                    coilBytes[byteIndex] |= (byte)(1 << bitIndex); // 按 LSB-first 规则打包
                }
            }

            return coilBytes;
        }

        /// <summary>
        /// 将 CheckedListBox 中选中的寄存器值打包成 Modbus 保持寄存器字节数组
        /// </summary>
        private byte[] PackRegisters(CheckedListBox checkedListBox, int regCount)
        {
            List<byte> regBytes = new List<byte>();

            for (int i = 0; i < regCount; i++)
            {
                ushort value = 0;
                if (i < checkedListBox.Items.Count && checkedListBox.GetItemChecked(i))
                {
                    // 解析 " = xxx" 的寄存器值
                    string itemText = checkedListBox.Items[i].ToString();
                    string[] parts = itemText.Split(new string[] { " = " }, StringSplitOptions.None);
                    if (parts.Length == 2 && ushort.TryParse(parts[1], out ushort regValue))
                        value = regValue;
                }

                // 高字节在前，低字节在后
                regBytes.Add((byte)(value >> 8));
                regBytes.Add((byte)(value & 0xFF));
            }

            return regBytes.ToArray();
        }



        private void Mutiple_reg_write_Click(object sender, EventArgs e)
        {
            if (tcpClient == null || !tcpClient.Connected)
            {
                MessageBox.Show("请先连接到服务器。");
                return;
            }

            byte functionCode;

            switch (reg_mul_write_kind.Text)
            {
                case "Reg_Coil":
                    functionCode = 0x0F; // 写多个线圈
                    break;
                case "Reg_Holding":
                    functionCode = 0x10; // 写多个保持寄存器
                    break;
                default:
                    MessageBox.Show("未知寄存器类型");
                    return;
            }

            transactionId++;

            // 公共部分
            List<byte> request = new List<byte>();

            // 事务ID
            request.Add((byte)(transactionId >> 8));
            request.Add((byte)(transactionId & 0xFF));

            // 协议ID
            request.Add(0);
            request.Add(0);

            // 占位符，长度稍后填充
            request.Add(0);
            request.Add(0);

            // 单元ID
            request.Add(1);

            // 功能码
            request.Add(functionCode);

            // 起始地址
            ushort startAddress = 0;
            if (ushort.TryParse(reg_start_addr.Text, out ushort parsedAddr))
                startAddress = parsedAddr;

            request.Add((byte)(startAddress >> 8));
            request.Add((byte)(startAddress & 0xFF));

            // ================= 写多个线圈 =================
            if (functionCode == 0x0F)
            {
                int coilCount = checkedListBox1.Items.Count;
                if (coilCount == 0)
                {
                    MessageBox.Show("没有线圈可写入");
                    return;
                }

                byte[] coilData = PackCoils(checkedListBox1, coilCount);
                int byteCount = coilData.Length;

                // 线圈数量
                request.Add((byte)(coilCount >> 8));
                request.Add((byte)(coilCount & 0xFF));

                // 字节计数
                request.Add((byte)byteCount);

                // 数据
                request.AddRange(coilData);
            }

            // ================= 写多个保持寄存器 =================
            else if (functionCode == 0x10)
            {
                int regCount = checkedListBox1.Items.Count;
                if (regCount == 0)
                {
                    MessageBox.Show("没有寄存器可写入");
                    return;
                }

                byte[] regData = PackRegisters(checkedListBox1, regCount);
                int byteCount = regData.Length; // regCount * 2

                // 写入寄存器数量
                request.Add((byte)(regCount >> 8));
                request.Add((byte)(regCount & 0xFF));

                // 字节计数
                request.Add((byte)byteCount);

                // 数据
                request.AddRange(regData);

                // ⚠️ 修复长度计算：UnitID + 功能码 + (后续字节数)
                ushort length = (ushort)(1 + 1 + 2 + 2 + 1 + byteCount);
                request[4] = (byte)(length >> 8);
                request[5] = (byte)(length & 0xFF);
            }


            // 发送
            NetworkStream stream = tcpClient.GetStream();
            byte[] reqBytes = request.ToArray();
            stream.Write(reqBytes, 0, reqBytes.Length);
            stream.Flush();
        }

        private void reg_start_addr_TextChanged(object sender, EventArgs e)
        {

        }

        private void groupBox1_Enter(object sender, EventArgs e)
        {

        }

        private void button2_Click_1(object sender, EventArgs e)
        {
             Data configForm = new Data(this,tcpClient);
            configForm.ShowDialog(); // 以对话框形式显示
        }


    }

}

    
